#include "udp.h"
#include <thread>
#include "AutoFree.h"
#include <string>
#include "utils.h"

std::string HP_GetIPAddress(char *url)
{
	if (url == nullptr || strlen(url) == 0)
	{
		return "0.0.0.0";
	}
	struct hostent *ip = gethostbyname(url);
	if (ip && ip->h_addrtype == AF_INET)
	{
		std::string retip;
		struct in_addr addr;
		addr.s_addr = *(u_long *)ip->h_addr_list[0];
		retip = inet_ntoa(addr);
		return retip;
	}
	return "0.0.0.0";
}
int Udp_Create(int port)
{
	sockaddr_in addr = {0};
	int len;
	SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");
	if (::bind(sockfd, (sockaddr *)&addr, sizeof(&addr)) == SOCKET_ERROR)
	{
		closesocket(sockfd);
		return OP_ERROR;
	}
	if (getsockname(sockfd, (sockaddr *)&addr, &len) != 0)
	{
		closesocket(sockfd);
		return OP_ERROR;
	}
	port = htons(addr.sin_port);
	std::thread thd(Udp_OnReceive, sockfd, 0);
	thd.detach();
	return OP_SUCCESS;
}
void Udp_OnReceive(int fd, int ptr)
{
	char buffer[MAX_BUF_LEN] = {0};
	int len = 0;
	sockaddr_in addr;
	int fromLen = 0;
	int Lport = -1;
	char *Ladder = NULL;
	while (len != -1)
	{
		len = recvfrom(fd, buffer, MAX_BUF_LEN, 0, (sockaddr *)&addr, &fromLen);
		if (len > 0)
		{
			if (memcmp(buffer, "000", 3) == 0)
			{
				Ladder = inet_ntoa(addr.sin_addr);
				Lport = htons(addr.sin_port);
			}
			UdpPackParseEx(fd, Ladder, Lport, buffer, len,
						   inet_ntoa(addr.sin_addr), htons(addr.sin_port));
		}
	}
}
bool Udp_SendToServer(int fd, char *remoteip, int remoteport, char *bufer, int len)
{
	return 0;
}
bool Udp_SendToClient(int fd, char *localip, int localport,
					  char *remoteip, int remoteport, char *bufer, int len)
{
	return 0;
}
void (*_func_ConsumerUdp_SendToServer)(int fd, char *laddr, int lport, char *buffer, int len);
void (*_func_ConsumerUdp_SendToClient)(int fd, char *localip, int localport,
									   char *remoteip, int remoteport, char *bufer, int len);
void UdpPackParseEx(int fd, char *laddr, int lport, char *buffer, int len,
					char *raddr, int rport)
{
	char remoteip[32] = {0};
	int remoteport = 0;
	int dlen = 0;
	if (memcmp(buffer, "000", 3) == 0)
	{
		if (buffer[3] == '1') //ip
		{
			//remoteip = *(int*)&buffer[4];
			memcpy(remoteip, &buffer[4], 4);
			remoteport = *(short *)&buffer[8];
			remoteport = ntohs(remoteport);
			buffer += 10;
			len -= 10;
		}
		else if (buffer[3] == '3') // ����
		{
			if (len > 5)
			{
				dlen = *(int *)&buffer[4];
				if (dlen > 0)
				{
					AutoFree url(dlen + 1);
					memcpy(url(), buffer + 5, dlen);
					remoteport = *(short *)&buffer[dlen + 6];
					remoteport = ntohs(remoteport);
					dlen += 7;
					buffer += dlen;
					std::string tmpip = HP_GetIPAddress(url());
					memcpy(remoteip, tmpip.c_str(), tmpip.length());
				}
			}
		}
		else
		{
			return;
		}
		if (_func_ConsumerUdp_SendToServer)
		{
			_func_ConsumerUdp_SendToServer(fd, remoteip, remoteport, buffer, len);
		}
		else
		{
			Udp_SendToServer(fd, remoteip, remoteport, buffer, len);
		}
	}
	if (_func_ConsumerUdp_SendToClient)
	{
		_func_ConsumerUdp_SendToClient(fd, laddr, lport, raddr, rport, buffer, len);
	}
	else
	{
		Udp_SendToClient(fd, laddr, lport, raddr, rport, buffer, len);
	}
}